Fork me on GitHub

《流畅的Python》读书笔记----第二章 序列构成的数组

[toc]

第二章 序列构成的数组

Python内置序列类型

两种分类:

  • 容器序列:这些序列能存放不同类型的数据,并且存放的是它们所包含的对象的引用,比如list,tuple,collection.deque
  • 扁平序列:这类序列只能容纳一种数据类型,是一段连续的内存空间,比如str,bytes,bytearray,memoryview,array.array

按照元素能否被修改分类:

  • 可变序列:list,collection.deque,bytearray,memoryview,array.array
  • 不可变序列:str,tuple,bytes

列表推导式和生成器表达式

列表推导式的例子

1
2
3
4
5
6
7
symbols = 'abd79u'
codes = [ord(symbol) for symbol in symbols]

# 等价的for循环
codes = []
for symbol in symbols:
codes.append(ord(symbol))

使用列表推导式的一般原则:

  1. 只用列表推导式创建列表,并尽量保持简洁
  2. 如果列表推导式超过两行,最好使用for loop

列表推导式与filter和map的比较

例子:

1
2
3
4
symbols = 'abd79u'
beyond_ascii = [ord(s) for s in symbols if ord(s)>127]
# 用filter和map实现
beyond_ascii = list(filter(lambda x: x>127,map(ord,symbols)))

函数map有两个参数,第一个参数为函数名,第二个列表,函数将会作用于列表的每个元素,然后返回作用后的列表。filter也是两个参数,第一个为用于筛选的函数。

生成表达式

把列表推导式的[]改成(),表达式就变为了生成表达式,列表推导式与生成表达式的区别在于,若想要迭代一个按规则生成的序列,列表推导式会一次性地生成整个列表,然后将其保存在内存中,而生成表达式只有要迭代到某个元素的时候,才会去生成这个元素,并没有事先建立一个完整的列表,这样做可以大大的节省内存。

元组不仅仅是不可变的列表

元组拆包

元组拆包可以应用到任何可迭代对象上,但是可迭代对象元素数量必须跟接受这些元素的元组的空档数一样,可以用*忽略多余的元素。
例子

1
2
3
4
5
6
7
8
9
name,age = (tengfei,25)
# *运算符可以把一个可迭代对象拆开作为函数的参数
t = (25,3)
divmod(*t)
# 输出:(8,1),商和余数

# 平行赋值
a,b,*rest = range(5)
# a:0,b:1,rest:[2,3,4]

具名元组namedtuple

它可以用来构建一个带字段名的元组和一个有名字的类。

1
2
3
4
5
6
7
8
9
>>> from collections import namedtuple
# 需要两个参数:类名,类的各个字段的名字。后者可由数个字符串组成可迭代的对象或者用空格分开
>>> City = namedtuple('City','name country population coordinates')
>>> beijing = City('Beijing','China',1000,(35,110))
# 可以使用.或者索引来获取字段的信息
>>> beijign.country
'China'
>>> beijing[1]
'China'

切片

s[a:b:c],在a,b之间以间隔c取值。当使用s[a:b:c]取值的时候,Python会自动调用s.__getitem__(slice[a:b:c])

切片赋值

如果赋值的对象是一个切片,那么赋值语句的左边必须是一个可迭代的对象,即使只有一个值。

使用+和*

需要注意的是,a*n语句中,如果a里的元素是其他可变对象的引用,比如a里的元素是list,比如a=[[1]],那么a = a*3语句得到的是包含3个引用的列表[[1],[1],[1]],如果要修改a中的某个元素,比如a[1][0]=2,那么会得到a变为[[2],[2],[2]]

序列的增量赋值+=和*=

当使用+=或*=时,Python会自动调用__iadd____imul__

list.sort方法和内置函数sorted

list.sort会对列表就地排序,它的返回值是None,所以不能使用max(list.sort)等串联的用法。sorted(list)会对list进行排序,并返回排序后的结果,但不是原地的,也就是list并不会发生改变。

它俩都有一个key参数,这个参数接受一个只有一个参数的函数(比如len,srt.lower),这个函数作用于list的每一个元素,并返回一个结果,sorted就按照这个返回的结果给list排序。

当列表不是首选时

实际应用中,除了list,在一些特殊的场景中,可以使用其他的序列结构,以提高效率。比如

  • 存储浮点数可以使用array
  • 如果需要频繁的先进先出操作,可以选择使用deque
  • 如果频繁需要检查一个元素是否在集合中,可以选择set